package ca.intelliware.commons.virtualization.vmware;

import java.io.IOException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import ca.intelliware.commons.virtualization.CenterServer;
import ca.intelliware.commons.virtualization.Explorer;
import ca.intelliware.commons.virtualization.VMachine;
import ca.intelliware.commons.virtualization.VirtualMachineGroup;

import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.mo.ManagedObject;
import com.vmware.vim25.mo.ServiceInstance;

public class VmwareVmExplorer implements Explorer {

	private List<ServiceInstance> serviceInstances = new ArrayList<ServiceInstance>();
	private List<VirtualMachineGroup> virtualMachineGroups = new ArrayList<VirtualMachineGroup>();

	
	private static VmwareVmExplorer explorer;
	
	private VmwareVmExplorer() {}
	
	public static VmwareVmExplorer getInstance() {
		if (explorer == null) {
			explorer = new VmwareVmExplorer();
		}
		return explorer;
	}
	
	
	
	void setVirtualMachineGroups(List<VirtualMachineGroup> virtualMachineGroups) {
		this.virtualMachineGroups = virtualMachineGroups;
	}

	public String inventoryReport() throws Exception {
		StringBuilder strBuilder = new StringBuilder();
		strBuilder.append("VM Explorer Inventory Report\n\n");
		for (CenterServer vCenterServer : centerServers()) {
			strBuilder.append(vCenterServer.inventoryReport());
		}
		return strBuilder.toString();
	}

	static ArrayList<ManagedObject> findManagedObjectsByType(
			ManagedObject[] managedObjects, String type)
			throws InvalidProperty, RuntimeFault, RemoteException {
		ArrayList<ManagedObject> foundManagedObjects = new ArrayList<ManagedObject>();
		for (ManagedObject child : managedObjects) {
			if (child.getMOR().getType().equals(type)) {
				foundManagedObjects.add(child);
			}
		}
		return foundManagedObjects;
	}

	public void addNewCenterServer(String centerServerUrl, String username,
			String password) throws IOException {
		addNewCenterServer(new URL(centerServerUrl), username, password);
	}

	public void addNewCenterServer(URL centerServerUrl, String username,
			String password) throws IOException {
		if (!containsCenterServer(centerServerUrl)) {
			List<ServiceInstance> newServiceInstances = new ArrayList<ServiceInstance>(
					this.serviceInstances.size() + 1);
			newServiceInstances.addAll(serviceInstances);
			newServiceInstances.add(new ServiceInstance(centerServerUrl,
					username, password, true));
			this.serviceInstances = newServiceInstances;
		}
	}

	public boolean containsCenterServer(URL centerServerUrl) throws IOException {
		boolean found = false;
		for (CenterServer centerServer : centerServers()) {
			if (centerServer.getUrl().equals(centerServerUrl)) {
				found = true;
				break;
			}
		}
		return found;
	}

	public CenterServer centerServer(URL centerServerUrl) throws IOException {
		
		CenterServer foundCenterServer = null; 
			
		for (CenterServer vCenterServer : centerServers()) {
			if (vCenterServer.getUrl().equals(centerServerUrl)) {
				foundCenterServer = vCenterServer;
				break;
			}
		}
		return foundCenterServer;
	}
	

	public List<CenterServer> centerServers() throws IOException {
		
		List<ServiceInstance> currentServiceInstances = this.serviceInstances;
		List<CenterServer> vCenterServers = new ArrayList<CenterServer>();
		for (int i = 0; i < currentServiceInstances.size(); i++) {
			ServiceInstance serviceInstance = currentServiceInstances.get(i);
			VmCenterServer centerServerCenter = new VmCenterServer(serviceInstance);
			vCenterServers.add(centerServerCenter);
		}
		return vCenterServers;
	}

	@Override
	public void revertAllVirtualMachinesToLastSnapshot() throws Exception {
		for (CenterServer centerServer : centerServers()) {
			centerServer.revertAllVirtualMachinesToLastSnapshot();
		}
	}

	@Override
	public VirtualMachineGroup virtualMachineGroup(String groupId) {
		VirtualMachineGroup found = null;
		for (VirtualMachineGroup vmGroup : virtualMachineGroups()) {
			if (vmGroup.getId().equalsIgnoreCase(groupId)) {
				found = vmGroup;
				break;
			}
		}
		return found;
	}

	@Override
	public List<VirtualMachineGroup> virtualMachineGroups() {
		return this.virtualMachineGroups;
	}

	@Override
	public List<VMachine> virtualMachine(String id) throws Exception {
		List<VMachine> virtualMachines = new ArrayList<VMachine>();
		for (CenterServer centerServer : centerServers()) {
			virtualMachines.addAll(centerServer.virtualMachine(id));
		}
		return virtualMachines;
	}

}
